class Logger {
  final String name;

  // 缓存已创建的对象
  static final Map<String, Logger> _cache = <String, Logger>{};

  factory Logger(String name) {
    return _cache.putIfAbsent(name, () => Logger._internal(name));
  }

  Logger._internal(this.name) {
    print("生成新实例：$name");
  }
}

void test() {
  var p1 = new Logger("1");
  var p2 = new Logger('22');
  var p3 = new Logger('1'); // 相同对象直接访问缓存
  //identical会对两个对象的地址进行比较，相同返回true，
  //等同于 == ，好处是如果重写了==，那用identical 会更方便。
  print(identical(p1, p3));
  print(identical(p1, p2));

  p1 ??= p3;
  print(p1 is Logger);
  print(p1 is! Logger);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
abstract class Animal {
  String name;

  void getNoise();

  factory Animal(String type, String name) {
    switch (type) {
      case "cat":
        return new Cat(name);
      case "dog":
        return new Dog(name);
      default:
        throw "The '$type' is not an animal";
    }
  }
}

class Cat implements Animal {
  String name;

  Cat(this.name);

  @override
  void getNoise() {
    print("${this.name}: mew~");
  }
}

class Dog implements Animal {
  String name;

  Dog(this.name);

  @override
  void getNoise() {
    print("${this.name}: wang~");
  }
}

int test2() {
  var cat = new Animal("cat", "wiki");
  var dog = new Animal("dog", "baobao");
  cat.getNoise();
  dog.getNoise();
  return 0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
// 单例-isolate 每个都不一样
class Singleton {
  static final Singleton _singleton = Singleton._internal();

  factory Singleton() {
    return _singleton;
  }

  Singleton._internal();
}

test3() {
  var s1 = Singleton();
  var s2 = Singleton();
  print(identical(s1, s2));
}
/////////////////////////////////////////////////////////////////////////////////////////////////////

void main() {
  test();
  test2();
  test3();
}
